package cz.muni.fi.pb138;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;

public class BiographyLoginModule implements LoginModule {

        private CallbackHandler handler;
        private Subject subject;
        private UserPrincipal userPrincipal;
        private RolePrincipal rolePrincipal;
        private String login;
        private List<String> userGroups;
        private AuthTest authTest;
        private static int userID;
        
        public int getUserID() {
            
            return userID;
        }

        public BiographyLoginModule() {
        }
        
        
        

        @Override
        public void initialize(Subject subject, CallbackHandler callbackHandler,
                        Map<String, ?> sharedState, Map<String, ?> options) {

                handler = callbackHandler;
                this.subject = subject;
                System.setProperty("java.security.auth.login.config", "jaas.config");
        }

        @Override
        public boolean login() throws LoginException {

                Callback[] callbacks = new Callback[2];
                callbacks[0] = new NameCallback("login");
                callbacks[1] = new PasswordCallback("password", true);

                try {
                        authTest = new AuthTest();
                        handler.handle(callbacks);
                        String name = ((NameCallback) callbacks[0]).getName();
                        String password = String.valueOf(((PasswordCallback) callbacks[1])
                                        .getPassword());

                        // Here we validate the credentials against some
                        // authentication/authorization provider.
                        // It can be a Database, an external LDAP, a Web Service, etc.
                        // For this tutorial we are just checking if user is "user123" and
                        // password is "pass123"
                        if (authTest.authenticate(name,password)) {
                                login = name;
                                userGroups = new ArrayList<String>();
                                userGroups.add("admin");
                                userID = authTest.getUserID(name);
                                return true;
                        }

                        // If credentials are NOT OK we throw a LoginException
                        throw new LoginException("Authentication failed");

                } catch (IOException e) {
                        throw new LoginException(e.getMessage());
                } catch (UnsupportedCallbackException e) {
                        throw new LoginException(e.getMessage());
                } catch (SAXException | ParserConfigurationException e) {
                        throw new LoginException(e.getMessage());
                }

        }

        @Override
        public boolean commit() throws LoginException {

                userPrincipal = new UserPrincipal(login);
                subject.getPrincipals().add(userPrincipal);

                if (userGroups != null && userGroups.size() > 0) {
                        for (String groupName : userGroups) {
                                rolePrincipal = new RolePrincipal(groupName);
                                subject.getPrincipals().add(rolePrincipal);
                        }
                }

                return true;
        }

        @Override
        public boolean abort() throws LoginException {
                return false;
        }

        @Override
        public boolean logout() throws LoginException {
                subject.getPrincipals().remove(userPrincipal);
                subject.getPrincipals().remove(rolePrincipal);
                return true;
        }

}